https://mp.weixin.qq.com/s/BZiWBspTMryrws21oxxEBg
使用Performance Timing API 中的相关指标来计算首屏加载时间
// 获取导航开始时间
const navigationStart = performance.timing.navigationStart;

// 获取DOMContentLoaded事件结束时间
const domContentLoadedEventEnd = performance.timing.domContentLoadedEventEnd;

// 计算首屏加载时间
const FCP = domContentLoadedEventEnd - navigationStart

https://blog.csdn.net/Zong_0915/article/details/131247138
一、拆包
  1.network分析，发现主要问题在3.3M的umj.[hash].js上，决定采用分包的策略。
  2.由于考虑到项目中react-file-viewer依赖较大，将它单独抽取出来。其余依赖在另外一个文件。
  （umi.js本身还是会存在的，只不过它里面大部分的内容被“转移”到这2个js文件中） 
  `webpack-bundle-analyzer` 插件来分析打包后的文件体积，可以找出体积较大的模块，并进行优化。


  补充知识：
  Webpack splitChunk 插件满足下述条件时，自动进行代码分割：
  可以被共享的（即重复被引用的）模块或者 node_modules 中的模块；
  在压缩前体积大于 30KB 的模块；
  在按需加载模块时，并行加载的模块不得超过 5 个；o 0
  在页面初始化加载时，并行加载的模块不得超过 3 个。

在配置里面添加配置项 chainWebpack，config.optimization.splitChunks
chainWebpack: (config) => {
  config.optimization.splitChunks({
    chunks: 'all',
    minSize: 30000,
    minChunks: 1,
    maxSize: 0,
    automaticNameDelimiter: '.',
    name: true,
    maxAsyncRequests: 30,
    maxInitialRequests: 10,
    cacheGroups: {
      
    }
  });
}
cacheGroups 选项用于配置缓存组
cacheGroups:{
  vendors: {
    name: 'vendors',
    test: /[\\/]node_modules[\\/]/,
    priority: 11
  },
  reactFileViewer: {
    name: 'reactFileViewer',
    test: /(react-file-viewer)/,
    priority: 12
  },
}
umiJs中的相关依赖拆成了两个JS文件 （umi.js本身还是会存在的，只不过它里面大部分的内容被“转移”到这俩js文件中） 因为react-file-viewer这个依赖它占用的大小非常非常的大，因此把他抽出来。

二、分析dist目录发现部分图片资源过大，最大的竟然达到400kb,对于图片较大的模块采用CDN，其余图片，常用的图片压缩为gzip压缩
由于考虑到使用在线服务手动压缩图片比较麻烦，可以直接在构建流程中加入压缩图片。
决定在webpack中使用image-webpack-loader插件实现。压缩后图片变成了几kb。
/ webpack.config.js
const path = require('path');
 
module.exports = {
  // ...
  module: {
    rules: [
      // ...
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        use: [
          'file-loader',
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65
              },
              optipng: {
                enabled: false,
              },
              pngquant: {
                quality: [0.65, 0.90],
                speed: 4
              },
              gifsicle: {
                interlaced: false,
              },
              webp: {
                quality: 75
              }
            }
          }
        ]
      }
      // ...
    ]
  },
  // ...
}

https://mp.weixin.qq.com/s/lHYkY-BOnxl8URY6-o57FA
静态资源本地缓存
后端返回资源问题：

采用HTTP缓存，设置Cache-Control，Last-Modified，Etag等响应头

采用Service Worker离线缓存

前端合理利用localStorage
三、组件按需加载减少资源加载大小以及数量，提升首屏加载速度。
React.lazy 或者使用import动态导入组件。
问题：实际场景，点开导入文件弹窗，等待了4s左右，该方法虽然提升了首屏加载速度，但是导致用户在后续使用中体验断层，甚至白屏的情况。
解决，还需要配合 预加载，让被加载的组件提前进入资源请求，而不是渲染时请求以减少资源请求时间。
思考：
1.react-lodable,不强依赖<Suspense>,可独立渲染<LazyComponent>,提供preload预加载方案。
  问题：模块过多，侵入的代码过多，重复且冗余，同时被预加载的模块没有进行统一管理，不利于后续维护。
2. route-resource-preload由于在webpack编译层面是可以获取到chunk的详细信息的，
是不是可以在plugin层面对按需加载的chunk进行统一维护，减少侵入式的代码。
其具备的特性，
1.拆分模块进行按需加载，减少首屏资源加载，提升用户体验。内部提供了一个dynamic，拆分组件代码并进行动态渲染。
2.支持组件资源批量进行预加载。可自定义触发时机，同时支持手动预加载，支持批量和单个组件。

开启GZip压缩
拆完包之后，我们再用gzip做一下压缩 安装compression-webpack-plugin


四、优化 JavaScript 加载，使用 async 和 defer 属性异步加载 JavaScript，减少阻塞渲染的脚本

五、静态资源本地缓存
后端返回资源问题：

采用HTTP缓存，设置Cache-Control，Last-Modified，Etag等响应头

采用Service Worker离线缓存

前端合理利用localStorage
其他方案，
1.使用现代化图片格式, WebP 和 AVIF 是相对较新的图像格式，相比传统的 JPEG 和 PNG 格式，它们提供了更高的压缩效率
2.nginx开启http2
